﻿using System.Collections;
using System.Linq;
using System.Collections.Generic;
using Moria.Common.Enum;
using Redbrick.Silverlight.Common;
using System;
using Redbrick.Silverlight.Serialization;

namespace Moria
{
    public class StatChangedEventArgs : EventArgs
    {
        public StatChangedEventArgs(Stat stat, int oldValue, int newValue)
        {
            this.Stat = stat;
            this.OldValue = OldValue;
            this.NewValue = newValue;
        }
        public Stat Stat { get; private set; }
        public int OldValue { get; private set; }
        public int NewValue { get; private set; }
    }

    public class StatCollection : Observable, IEnumerable<int>
    {

        #region Consts & Settings

        private const int StatSize = 6;

        #endregion Consts & Settings

        #region Declarations

        int[] _values = new int[StatSize];

        #endregion Declarations

        #region Constructor
        static StatCollection()
        {
			  SilverlightSerializer.RegisterSerializationAssembly();
        }
        public StatCollection()
        {
			  this.DebugMethodInfo();
			  for (int i = 0; i < _values.Length; i++)
                this[i] = 0;
        }
        public StatCollection(int[] values)
        {
 			  this.DebugMethodInfo(values);
           for (int i = 0; i < _values.Length; i++)
            {
                if (i < values.Length) this[i] = values[i];
                else this[i] = 0;
            }
        }

        #endregion Constructor

        #region Methods

        private int Get(int ndx)
        {
			  this.DebugMethodInfo(ndx);
			  return this._values[ndx % StatSize];
        }
        private void Set(int ndx, int value)
        {
			  this.DebugMethodInfo(ndx,value);
			  int oldVal = Get(ndx);
            if (value == oldVal) return;
            this._values[ndx % StatSize] = value;
            RaisePropertyChanged(((Stat)ndx).Description());
            var handler = this.StatUpdated;
            if (handler != null)
                handler(this, new StatChangedEventArgs((Stat)ndx, oldVal, value));
        }
        public void Add(int value)
        {
			  this.DebugMethodInfo(value);
			  // nothing to see here, added so xml serialization will work 
        }
        public static implicit operator StatCollection(int[] ary)
        {
            return new StatCollection(ary);
        }
        public int[] ToArray() { return this._values; }
        public int this[int n]
        {
            get { return this.Get(n); }
            set { this.Set(n, value); }
        }
        public int this[Stat n]
        {
            get { return this.Get(n.Int()); }
            set { this.Set(n.Int(), value); }
        }

        public IEnumerator<int> GetEnumerator()
        {
            for (int i = 0; i < _values.Length; i++)
            {
                yield return _values[i];
            }
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        #endregion Methods

        #region Events

        public event EventHandler<StatChangedEventArgs> StatUpdated;

        #endregion Events

        #region Properties

        public int Count { get { return this._values.Length; } }

        #endregion Properties
    }

    [Serializer(typeof(StatCollection))]
    public class StatCollectionSerializer : ISerializeObject
    {
        public object[] Serialize(object target)
        {
            StatCollection stats = target as StatCollection;
            if (stats != null)
            {
                object[] ot = new object[stats.Count];
                stats.ForEach( (ndx,val) => ot[ndx] = val);
                return ot;
            }
            return null;
        }

        public object Deserialize(object[] data)
        {
            StatCollection stats = new StatCollection();
            if (stats != null)
            {
                data.ForEach( (ndx,val)=>stats[ndx]=(int)val );
                return stats;
            }
            return null;
        }
    }
}
